Kelsey Shi

返回

第三章学习笔记-应用中的数据

#dev# #study#
发布于 2024-04-23

100 小时后请叫我苹果开发者

数据

@State

状态仅在当前定义所处的视图结构中有效(父级花括号内)。

@Binding

将父级视图结构中的信息传递到子级视图结构中。其作用并非创建一个新数据,而是单纯地将子级别视图中的信息与父视图结构的信息捆绑在一起。

struct ViewOne: View {
@State var userInput = ""
var body: some View {
ViewTwo(userInput: $userInput )
}
}
struct ViewTwo: View {
// 绑定传递到的变量 userInput
@Binding var userInput: String
var body: some View {
TextField("请输入用户名",text: $userInput)
.textFieldStyle(RoundedBorderTextFieldStyle())
.padding()
}
}

@Environment

查询文档: EnvironmentValues | Apple Developer Documentation

写法: @Enviroment(\.valueName) var valueName

修改: 两种写法都可以

.enviroment(\.valueName, newValue)

.valueName(newValue)

@main
struct ForCreatorLifyCycleApp: App {
@Enviroment(\.scenePhase) private var scenePhase
// 修改
EntryModalView()
.enviroment(\.allowsTightening, true)
.allowsTightening(true)
}

监测

可观察对象 ObservableObject 和发布器 @Published

可观察对象 ObservableObject 是一个协议 Protocol,该协议中要求所有遵守该协议的类必须包含发布器,当数据发生改变时,发布器会将被改变的信息传递出去。与其相对应的,属性包装器 @Published 的用途是标注哪些数据被改变时需要被发送,当数据改变时,发布器会自动将最新数据推送至所有订阅的视图中。

// 协议 ObservableObject
class Data: ObservableObject {
//发布器 @Published
@Published var article = "一篇文章"
}

观察对象 @ObservedObject

观察对象指的是放置在视图文件中,用于订阅可观察对象的属性包装器。

struct ReactedView: View {
// 订阅可观察对象Data
@ObservedObject var data: Data
var body: some View {
Text(data.article)
}
}
@main
struct SwiftUIViewsApp: App {
// 初始化数据
let data = Data()
var body: some Scene {
WindowGroup {
ReactedView(data: data)
}
}
}

@ObservedObject 缺陷与变种:

  1. 初始化步骤稍显繁琐,能直接在需要用到的视图里直接初始化就会更方便。 -> @StateObject
  2. 不适合跨视图使用。 -> @EnvironmentObject

状态对象 @StateObject

受限于 SwiftUI 的视图更新机制,若在视图中初始化 @ObservedObject 可能会造成异常刷新。为了解决这一问题,SwiftUI 可以负责协同初始化并管理该变量,新的属性包装器为 @StateObject

struct ReactedView: View {
// 订阅可观察对象Data
// @ObservedObject var data: Data
// 改为
@StateObject var data = Data()
var body: some View {
Text(data.article)
}
}

环境对象 @EnvironmentObject

解决 @ObservedObject 接力棒式数据传递。

具体写法如下,在最高层级的视图中把数据装到沙包里,写做.environmentObject(data) ,接着在任意子视图中接住沙包,写做@EnvironmentObject var data: Data便可以使用了。

// 考虑兼容 iOS 16 及之前的系统
struct ReactedView: View {
// 在任意子视图中接住沙包
@EnvironmentObject var data: Data
var body: some View {
Text(data.article)
}
}
@main
struct SwiftUIViewsApp: App {
// 订阅可观察对象Data
// @ObservedObject var data: Data
// 改为
@StateObject var data = Data()
var body: some Scene {
WindowGroup {
// 在最高层级的视图中把数据装到沙包里
ReactedView(data: data)
.environmentObject(data)
}
}
}
最后编辑于 Invalid DateTime